package com.cskaoyan.service;

import com.cskaoyan.exception.CouponEmptyException;
import com.cskaoyan.exception.CouponReceiveException;
import com.cskaoyan.mapper.CartMapper;
import com.cskaoyan.mapper.CouponMapper;
import com.cskaoyan.mapper.CouponUserMapper;
import com.cskaoyan.mapper.UserMapper;
import com.cskaoyan.model.bean.*;
import com.cskaoyan.model.bo.extend.CouponBo;
import com.cskaoyan.model.bo.extend.ListUserBo;
import com.cskaoyan.model.bo.extend.WXCouponBo;
import com.cskaoyan.model.bo.extend.WXCouponSelectBo;
import com.cskaoyan.model.vo.extend.CouponUserVo;
import com.cskaoyan.model.vo.extend.CouponVo;
import com.cskaoyan.model.vo.extend.WXCouponVo;
import com.cskaoyan.utils.CodeGenerateUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author：Chunk
 * @Description:
 * @Date Created in 17:14 2021/4/9
 */
@Service
public class CouponServiceImpl implements CouponService{
    @Autowired
    CouponMapper couponMapper;
    @Autowired
    CouponUserMapper couponUserMapper;
    @Autowired
    CartMapper cartMapper;
    @Autowired
    UserMapper userMapper;

    @Override
    public CouponVo queryCouponList(CouponBo couponBo) {

        PageHelper.startPage(couponBo.getPage(), couponBo.getLimit());

        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        if(couponBo.getName() != null && !"".equals(couponBo.getName())){
            criteria.andNameLike("%" + couponBo.getName() + "%");
        }
        if(couponBo.getType() != null && !"".equals(couponBo.getType())){
            criteria.andTypeEqualTo(couponBo.getType());
        }
        if(couponBo.getStatus() != null && !"".equals(couponBo.getStatus())){
            criteria.andStatusEqualTo(couponBo.getStatus());
        }
        couponExample.setOrderByClause(couponBo.getSort() + " " +couponBo.getOrder());
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);

        PageInfo<Coupon> couponPageInfo = new PageInfo<>(coupons);
        long total = couponPageInfo.getTotal();
        CouponVo couponVo = new CouponVo();
        couponVo.setTotal(total);
        couponVo.setItems(coupons);
        return couponVo;
    }

    @Override
    public Coupon update(Coupon coupon) {
        couponMapper.updateByPrimaryKeySelective(coupon);
        Coupon couponVo = couponMapper.selectByPrimaryKey(coupon.getId());
        return couponVo;
    }

    @Override
    public void delete(Coupon coupon) {
        coupon.setDeleted(true);
        couponMapper.updateByPrimaryKeySelective(coupon);
    }

    @Override
    public Coupon create(Coupon coupon) {
        if(coupon.getType() == 2){
            coupon.setCode(CodeGenerateUtils.generateShortUuid());
        }
        couponMapper.insertSelective(coupon);
        Coupon couponVo = couponMapper.selectByPrimaryKey(coupon.getId());
        return couponVo;
    }

    @Override
    public Coupon queryById(Integer id) {
        Coupon coupon = couponMapper.selectByPrimaryKey(id);
        return coupon;
    }

    @Override
    public CouponUserVo queryListUser(ListUserBo listUserBo) {
        PageHelper.startPage(listUserBo.getPage(), listUserBo.getLimit());
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        if(listUserBo.getCouponId() != null && !"".equals(listUserBo.getCouponId())){
            criteria.andCouponIdEqualTo(listUserBo.getCouponId());
        }
        if(listUserBo.getUserId() != null && !"".equals(listUserBo.getUserId())){
            criteria.andUserIdEqualTo(listUserBo.getUserId());
        }
        if(listUserBo.getStatus() != null && !"".equals(listUserBo.getStatus())){
            criteria.andUserIdEqualTo(listUserBo.getStatus());
        }

        couponUserExample.setOrderByClause(listUserBo.getSort() + " " + listUserBo.getOrder());
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);

        PageInfo<CouponUser> couponUserPageInfo = new PageInfo<>(couponUsers);
        long total = couponUserPageInfo.getTotal();
        CouponUserVo couponUserVo = new CouponUserVo();
        couponUserVo.setTotal(total);
        couponUserVo.setItems(couponUsers);
        return couponUserVo;
    }

    @Override
    public WXCouponVo queryWXCouponList(WXCouponBo wxCouponBo) {
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        if(wxCouponBo.getStatus() != null && !"".equals(wxCouponBo.getStatus())){
            criteria.andStatusEqualTo(wxCouponBo.getStatus().shortValue());
        }

        couponExample.setOrderByClause("discount asc");
        PageHelper.startPage(wxCouponBo.getPage(), wxCouponBo.getSize());
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        PageInfo<Coupon> couponPageInfo = new PageInfo<>();
        long total = couponPageInfo.getTotal();
        WXCouponVo wxCouponVo = new WXCouponVo();
        wxCouponVo.setCount(total);
        wxCouponVo.setData(coupons);
        return  wxCouponVo;
    }

    @Override
    public List<Coupon> selectWXCouponList(WXCouponSelectBo wxCouponSelectBo) {
        Cart cart = cartMapper.selectByPrimaryKey(wxCouponSelectBo.getCartId());
        Integer userId = null;
        if (cart != null) {
            userId = cart.getUserId();
        }

        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        if(userId != null){
            criteria.andUserIdEqualTo(userId);
        }
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);


        ArrayList<Integer> couponIds = new ArrayList<>();
        for (CouponUser couponUser : couponUsers) {
            Integer couponId = couponUser.getCouponId();
            couponIds.add(couponId);
        }
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria1 = couponExample.createCriteria();
        criteria1.andIdIn(couponIds);

        couponExample.setOrderByClause("add_time desc");
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        return coupons;
    }

    @Override
    @Transactional
    public void receiveWXCoupon(Integer id) throws CouponReceiveException, CouponEmptyException {
        String username = (String)SecurityUtils.getSubject().getPrincipal();
        Integer userId = userMapper.selectIdByUsername(username);
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        if(id != null && userId != null){
            criteria.andUserIdEqualTo(userId).andCouponIdEqualTo(id);
        }
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);
        if(couponUsers.size() != 0){
            throw new CouponReceiveException(740, "优惠券已经领取过");
        }

        Coupon coupon = couponMapper.selectByPrimaryKey(id);
        insertIntoCoupon(userId, coupon, id);
    }

    @Override
    public WXCouponVo queryWXMyCouponList(WXCouponBo wxCouponBo) {
        String username = (String)SecurityUtils.getSubject().getPrincipal();
        Integer userId = userMapper.selectIdByUsername(username);

        WXCouponVo wxCouponVo = new WXCouponVo();
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);
        //如果该用户没有优惠券直接返回
        if(couponUsers.size() == 0){
            return wxCouponVo;
        }

        ArrayList<Integer> couponIds = new ArrayList<>();
        for (CouponUser couponUser : couponUsers) {
            Integer couponId = couponUser.getCouponId();
            couponIds.add(couponId);
        }
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria1 = couponExample.createCriteria();
        criteria1.andIdIn(couponIds);
        if(wxCouponBo.getStatus() != null && !"".equals(wxCouponBo.getStatus())){
            criteria1.andStatusEqualTo(wxCouponBo.getStatus().shortValue());
        }
        PageHelper.startPage(wxCouponBo.getPage(), wxCouponBo.getSize());
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        PageInfo<Coupon> couponPageInfo = new PageInfo<>(coupons);
        long total = couponPageInfo.getTotal();
        wxCouponVo.setCount(total);
        wxCouponVo.setData(coupons);
        return wxCouponVo;
    }

    @Override
    public void exchangeWXCoupon(String code) throws CouponReceiveException, CouponEmptyException {
        String username = (String)SecurityUtils.getSubject().getPrincipal();
        Integer userId = userMapper.selectIdByUsername(username);

        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        if(code != null && !"".equals(code)){
            criteria.andCodeEqualTo(code);
        }
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        if(coupons.size() == 0){
            throw new CouponReceiveException(742, "优惠券不正确");
        }
        Coupon coupon = coupons.get(0);
        Integer couponId = coupon.getId();

        //去cskaoyanmall_coupon_user关系表查询当前用户是否有兑换券
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria1 = couponUserExample.createCriteria();
        if(couponId != null && userId != null){
            criteria1.andCouponIdEqualTo(couponId).andUserIdEqualTo(userId);
        }
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(couponUserExample);
        if(couponUsers.size() == 1){
            throw new CouponReceiveException(740, "优惠券已兑换");
        }
        //兑换优惠券，插入到数据库中
        insertIntoCoupon(userId, coupon, couponId);
    }

    private void insertIntoCoupon(Integer userId, Coupon coupon, Integer couponId) throws CouponEmptyException {
        Integer total = coupon.getTotal();
        if (total == 0) {
            throw new CouponEmptyException();
        }
        coupon.setTotal(total - 1);
        couponMapper.updateByPrimaryKeySelective(coupon);

        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(couponId);
        couponUser.setStartTime(coupon.getStartTime());
        couponUser.setEndTime(coupon.getEndTime());

        couponUserMapper.insertSelective(couponUser);
    }
}
